package com.start.workflow.core.manage;

import com.start.common.entity.StartBaseUser;
import com.start.common.entity.StartDicData;
import com.start.common.std.StartBaseSingleton;
import com.start.common.std.StartSingletonFactory;
import com.start.common.tools.SpringContextTools;
import com.start.workflow.common.std.IStartActCandidateLoad;
import com.start.workflow.entity.StartActBusinessEntity;
import com.start.workflow.entity.StartActModelConfig;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
 @Schema(name="用户任务候选人加载器")
public class StartActCandidateManager extends StartBaseSingleton<StartActCandidateManager> {
    private final Map<String, IStartActCandidateLoad> candidateLoadMap = new HashMap<>();

    /**
     * 处死化加载全部任务候选人加载器
     */
    public void init() {
        candidateLoadMap.clear();
        Map<String, IStartActCandidateLoad> beans = SpringContextTools.getBeans(IStartActCandidateLoad.class, false);
        if (beans == null || beans.isEmpty()) return;
        for (IStartActCandidateLoad load : beans.values()) {
            String actCandidateType = load.actCandidateType();
            if (StringUtils.isAllBlank(actCandidateType)) {
                log.error(load.getClass().getName() + " 未定义 actCandidateType");
                continue;
            }
            if (candidateLoadMap.containsKey(actCandidateType)) {
                IStartActCandidateLoad old = candidateLoadMap.get(actCandidateType);
                log.error(old.getClass().getName() + "," + load.getClass().getName() + "重复类型候选人类型：" + actCandidateType);
                continue;
            }
            candidateLoadMap.put(actCandidateType, load);
        }
    }

    /**
     * 获取当前实例
     *
     * @return
     */
    public static StartActCandidateManager getInstance() {
        return StartSingletonFactory.get(StartActCandidateManager.class);
    }

    /**
     * 加载流程任务候选人
     *
     * @param businessEntity 任务候选人处理类型
     * @param actModelConfig 处理人配置
     * @return List<StartBaseUser>
     */
    public List<StartBaseUser> loadCandidateUser(StartActBusinessEntity businessEntity, StartActModelConfig actModelConfig) {
        IStartActCandidateLoad candidateLoad = candidateLoadMap.getOrDefault(actModelConfig.getConfKey(), null);
        List<StartBaseUser> users = new ArrayList<>();
        if (candidateLoad == null || !candidateLoad.isGlobal()) return users;
        List<StartBaseUser> baseUsers = candidateLoad.load(businessEntity, actModelConfig);
        if (null == baseUsers) return users;
        return baseUsers;
    }

    public static List<StartBaseUser> getCandidateUser(StartActBusinessEntity businessEntity, StartActModelConfig actModelConfig) {
        if (actModelConfig == null) {
            return new ArrayList<>();
        }
        return StartActCandidateManager.getInstance().loadCandidateUser(businessEntity, actModelConfig);
    }


    /**
     * 获取全部候选人加载器
     *
     * @return
     */
    public static List<StartDicData> getDicData() {
        List<IStartActCandidateLoad> values = getInstance().candidateLoadMap.values().stream()
                .sorted(Comparator.comparingInt(IStartActCandidateLoad::order)).collect(Collectors.toList());

        Map<String, List<StartDicData>> childDicData = values.stream().
                collect(Collectors.groupingBy(IStartActCandidateLoad::categoryKey, Collectors.mapping(e -> {
                    StartDicData dicData = new StartDicData();
                    dicData.setLabel(e.actCandidateLabel());
                    dicData.setValue(e.actCandidateType());
                    dicData.setDesc(e.actCandidateDesc());
                    dicData.setOrder(e.order());
                    return dicData;
                }, Collectors.toList())));

        List<StartDicData> rootDic = new ArrayList<>();
        for (String key : childDicData.keySet()) {
            IStartActCandidateLoad first = values.stream().filter(e -> Objects.equals(e.categoryKey(), key)).findFirst().get();
            StartDicData root = new StartDicData();
            root.setLabel(first.categoryName());
            root.setValue(first.categoryName());
            root.setOrder(first.order());
            root.setGroups(childDicData.get(key));
            rootDic.add(root);
        }
        return rootDic;
    }


}
